package main

import (
	"fmt"
	"os"
	"path/filepath"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/layout"
	"fyne.io/fyne/v2/widget"

	"gitcode.com/shexk/fimqClient/core"
)

func NewEdit(holdtext string) *widget.Entry {
	text := widget.NewEntry()
	text.SetPlaceHolder(holdtext)
	return text
}

type LoginAck struct {
	id     uint64
	name   string
	result bool
	err    string
}

func ShowLoginWindows(app fyne.App, win fyne.Window, mainWin fyne.Window, client *FimqClient, connChan chan bool, loginChan chan *LoginAck) {
	bQuit := false
	bLogin := false
	//loginWin := app.NewWindow("Login")

	userText := widget.NewLabel("User ID")
	userEdit := NewEdit("User ID")
	user := container.NewGridWithColumns(2, userText, userEdit)
	userEdit.Text = "791129"

	pwdText := widget.NewLabel("User Password")
	pwdEdit := NewEdit("User Password")
	pwdEdit.Text = "123456"

	pwd := container.NewGridWithColumns(2, pwdText, pwdEdit)

	hitText := widget.NewLabel("State:")
	hitEdit := NewEdit("")

	hit := container.NewGridWithColumns(2, hitText, hitEdit)

	loginBtn := widget.NewButton("Login", func() {
		num, err := core.StringToUint64(userEdit.Text)
		if err == nil {
			if client != nil {
				client.Login(num, pwdEdit.Text)
			}
		}
	})
	cancelBtn := widget.NewButton("Cancel", func() {
		bQuit = true
		app.Quit()
	})
	btn := container.NewGridWithColumns(2, loginBtn, cancelBtn)

	main := container.NewVBox(user, pwd, hit, btn)

	win.SetContent(main)
	win.CenterOnScreen()
	win.Resize(fyne.NewSize(400, 150))

	go func() {
		for result := range connChan {
			fyne.Do(func() {
				if result {
					hitEdit.Text = "Connect Success"
				} else {
					hitEdit.Text = "Connect Fail"
				}
				hitEdit.Refresh()
			})
		}

	}()

	var userid uint64
	var username string
	go func() {
		for loginAck := range loginChan {
			userid = loginAck.id
			username = loginAck.name
			fyne.Do(func() {
				if loginAck.result {
					bLogin = true
					win.Close()
				} else {
					hitEdit.Text = loginAck.err
				}
				hitEdit.Refresh()
			})
		}
	}()

	win.SetOnClosed(func() {
		if !bQuit {
			if bLogin {
				ShowMainWindows(mainWin, userid, username, app, client)
			} else {
				app.Quit()
			}
		}
	})

	win.Show()
}
func GetDir(path string) []string {
	// 读取目录内容
	dirs := []string{}
	entries, err := os.ReadDir(path)
	if err != nil {
		return dirs
	}
	// 递归处理每个子项
	for _, entry := range entries {
		childPath := filepath.Join(path, entry.Name())
		dirs = append(dirs, childPath)
	}
	//fmt.Println(len(dirs))

	return dirs
}
func isDir(path string) bool {
	fi, err := os.Stat(path)
	if err != nil {
		return false
	}
	return fi.IsDir()
}
func ShowMainWindows(myWindow fyne.Window, id uint64, name string, app fyne.App, client *FimqClient) {
	myWindow.SetTitle("FIMQ Client-(ID:" + fmt.Sprintf("%d", id) + ",Name=" + name + ")")
	textinput := NewEdit("Publish Text")
	textinput.Text = "1024"
	textinput.OnChanged = func(s string) {

	}

	recvArea := widget.NewMultiLineEntry()
	recvArea.Wrapping = fyne.TextWrapBreak

	// 创建三个按钮
	clearBtn := widget.NewButton("Clear", func() {
		recvArea.SetText("")
	})

	stopBtn := widget.NewButton("Stop", func() {
		StopSendPublishMsgTick(client)
		// dialog.ShowConfirm("Confirm", "Are you sure?", func(confirmed bool) {
		// 	if confirmed {
		// 		//helloLabel.SetText("Confirmed!")
		// 	}
		// }, myWindow)
	})

	num := 0
	go func() {
		for buf := range core.GetLog().LogBus {
			fyne.Do(func() {
				// 安全执行
				if num >= 100 {
					recvArea.SetText("")
					num = 0
				}
				recvArea.SetText(buf + recvArea.Text)
			})
			num++
		}
	}()
	targetEdit := NewEdit("Target ClientID")
	targetEdit.Text = "791129"
	targetEdit.Disable()

	bTopic := false
	sendRadio := widget.NewRadioGroup([]string{"Topic", "P2P"}, func(s string) {
		if s == "Topic" {
			targetEdit.Disable()
			bTopic = true
		} else {
			targetEdit.Enable()
			bTopic = false
		}
	})
	sendRadio.SetSelected("Topic")
	sendRadio.Horizontal = true

	topictext := NewEdit("Topic Name")
	topictext.Text = "Test/Topic02"

	startBtn := widget.NewButton("Start", func() {
		value, err := core.StringToUint64(targetEdit.Text)
		if err != nil {
			value = 0
		}
		len1, err2 := core.StringToUint64(textinput.Text)
		if err2 != nil {
			len1 = 1024
		}
		StartSendPublishMsgTick(client, bTopic, topictext.Text, value, len1)
		//dialog.ShowInformation("Info", "This is an info dialog", myWindow)
	})
	// 创建按钮容器，使按钮并排显示
	loginContainer := container.New(layout.NewGridLayout(5),
		clearBtn,
		startBtn,
		stopBtn,
		sendRadio,
		targetEdit)

	bselect := false
	topicBtn := widget.NewButton("Register", func() {
		fyne.Do(func() {
			if bselect {
				client.SubscriberTopic([]string{topictext.Text})
			} else {
				client.UnSubscriberTopic([]string{topictext.Text})
			}

		})
	})
	topictext.OnChanged = func(s string) {

	}
	radio := widget.NewRadioGroup([]string{"Subs", "UnSubs"}, func(s string) {
		if s == "Subs" {
			topicBtn.SetText("Register")
			bselect = true
		} else {
			topicBtn.SetText("UnRegister")
			bselect = false
		}
	})
	radio.SetSelected("Subs")
	radio.Horizontal = true

	inputBtn := widget.NewButton("Publish", func() {
		len, _ := core.StringToUint64(textinput.Text)
		data, _ := core.GenerateRandomString(len)
		if sendRadio.Selected == "Topic" {
			client.PublishTopicMessage(topictext.Text, []byte(data), core.MQ_QOS_1)
		} else {
			if id, err := core.StringToUint64(targetEdit.Text); err != nil {
				core.GetLog().ShowMsg(core.Log_Debug, "please input targetid value,it must is number")
			} else {
				if id > 0 {
					client.PublishP2PMessage(id, []byte(data), core.MQ_QOS_1)
				} else {
					core.GetLog().ShowMsg(core.Log_Debug, "please input targetid value,it must >0")
				}
			}

		}

	})
	topicContainer := container.NewGridWithColumns(5, topictext, radio, topicBtn, textinput, inputBtn)

	root := "d:\\"
	tree := widget.NewTree(
		func(id widget.TreeNodeID) []widget.TreeNodeID {
			// if id == root {
			// 	return GetDir(root)
			// }
			if id == "" {
				return GetDir(root)
			}
			return GetDir(id)
		},
		func(id widget.TreeNodeID) bool {
			return id == "" || isDir(id)
		},
		func(branch bool) fyne.CanvasObject {
			if branch {
				return widget.NewLabel("Branch template")
			}
			return widget.NewLabel("Leaf template")
		},
		func(id widget.TreeNodeID, branch bool, o fyne.CanvasObject) {
			fileInfo, err := os.Stat(id)
			if err != nil {
				o.(*widget.Label).SetText(id)
			} else {
				o.(*widget.Label).SetText(fileInfo.Name())
			}
		},
	)
	tree.OnSelected = func(uid string) {
		println("选中文件:", uid)
	}

	abc := container.NewHSplit(tree, recvArea)
	abc.SetOffset(0.3)
	ss := container.NewScroll(abc)
	ss.SetMinSize(fyne.NewSize(600, 400))

	// 创建主容器，垂直排列按钮和文本框
	mainContainer := container.NewVBox(
		loginContainer,
		topicContainer,
		ss,
	)

	myWindow.SetFixedSize(true)

	// 设置窗口内容并显示

	myWindow.SetContent(mainContainer)
	myWindow.Resize(fyne.NewSize(600, 400)) // 设置初始窗口大小
	myWindow.CenterOnScreen()
	myWindow.Show()
}
func main() {
	myApp := app.New()
	loginWin := myApp.NewWindow("Login")
	mainWin := myApp.NewWindow("MainWindows")

	connectChan := make(chan bool, 100)
	loginChan := make(chan *LoginAck, 100)

	fimqClient := NewFimqClient()

	fimqClient.OnReceiveTopicMsg = func(msg *core.TopicMessage) {
		core.GetLog().ShowMsg(core.Log_Debug, "Topic Receive Message,Len=", len(msg.Payload))
	}

	fimqClient.OnReceiveP2PMsg = func(msg *core.P2PMessage) {
		core.GetLog().ShowMsg(core.Log_Debug, "P2P Receive Message,Len=", len(msg.Payload))
	}

	fimqClient.OnConnect = func(result bool, err string) {
		connectChan <- result
		if !result {
		}
	}
	fimqClient.OnLogin = func(id uint64, name string, result bool, err string) {
		loginChan <- &LoginAck{id: id, name: name, result: result, err: err}
	}
	fimqClient.OnSubscriberAck = func(msg *core.SubscriberAck) {
		for _, topic := range msg.Topics {
			core.GetLog().ShowMsg(core.Log_Debug, "Subs:", topic.Name, topic.Command, topic.Result, topic.Error)
		}
	}
	fimqClient.OnUnSubscriberAck = func(msg *core.SubscriberAck) {
		for _, topic := range msg.Topics {
			core.GetLog().ShowMsg(core.Log_Debug, "UnSubs:", topic.Name, topic.Command, topic.Result, topic.Error)
		}
	}

	fimqClient.ProcessMsgChan()

	fimqClient.ConnectFimqServer("ukhy3869454.vicp.fun:36546")
	//fimqClient.ConnectFimqServer("127.0.0.1:60000")

	//mainWin := myApp.NewWindow("Fimq Client")
	ShowLoginWindows(myApp, loginWin, mainWin, fimqClient, connectChan, loginChan)

	myApp.Run()
}

var TestTick *time.Ticker
var bStartTest bool = false

func StopSendPublishMsgTick(c *FimqClient) {
	if TestTick != nil {
		TestTick.Stop()
		TestTick = nil
		bStartTest = false
	}
}
func StartSendPublishMsgTick(c *FimqClient, bTopic bool, topicName string, clientid uint64, datalen uint64) {
	if bStartTest {
		return
	}
	go func() {
		bStartTest = true
		TestTick = time.NewTicker(time.Duration(100) * time.Millisecond)

		for range TestTick.C {
			buf, _ := core.GenerateRandomString(datalen)
			if bTopic {
				err := c.PublishTopicMessage(topicName, []byte(buf), core.MQ_QOS_1)
				if err != nil {
					core.GetLog().ShowMsg(core.Log_Debug, "Publish Msg Error:", err)
				}
			} else {
				err := c.PublishP2PMessage(clientid, []byte(buf), core.MQ_QOS_1)
				if err != nil {
					core.GetLog().ShowMsg(core.Log_Debug, "Publish Msg Error:", err)
				}
			}

		}
	}()
}

//Mac ../../bin/fyne package -os darwin -icon app.ico
//Win fyne package -os windows -icon app.ico
//linux fyne package -os linux -icon myapp.png
